#!/usr/bin/perl
use warnings;
use strict;
#use v5.9
#******************************************************************************
# File: 
#		perl.pl
# Recipe: 1.2
#		Establishing a Default Value
# Version:
#		0.1
# Author:
#   	Yubei Zhu
# Mail:
#		yubeizhu@gmail.com
# Created at:
#   	2012-08-15  
# Last Update:
#   	2012-08-16
# License: 
#		GPLv3	
#******************************************************************************


################################### Using Scalar ###################################

# use $sFirst if $sFirst is true, else $sSecond
my @aFirst = ( undef, 0, "0", 0.0, "0.0" , 00000, "00000", "", " ", 23, "32", [] );
my $sSecond = "backup";

# Pay attention to the values which are false
foreach my $sIndex ( 0 .. $#aFirst ){
	my $sFirst = $aFirst[ $sIndex ];	
	# use $sFirst if $sFirst is true, else $sSecond
	my $sDefaultValue = $sFirst || $sSecond; 
	if( $sFirst ){
		print "[ $sIndex ] I'm first: [$sDefaultValue]\n";
	}
	else{
		print "[ $sIndex ] I'm Second: [$sDefaultValue], first is  [$sFirst]\n";
	}
}

# Self reset method
my ( $sFlag, $sReset ) = ( 0, 1 );
$sFlag ||= $sReset;  # $sFlag = $sFlag || $sReset

# Only Regard undef as false
# Use defined and three-way test
my $sNotDefined = undef;
my $sDefaultValue = defined( $sNotDefined ) ? $sNotDefined : $sSecond ;
print "When using undef: $sDefaultValue\n";


# Test element from a list
my $sDir = $ARGV[ 0 ] or "/tmp"; # or: another form of ||
$sDir = defined( $ARGV[ 0 ] ) ? $ARGV[ 0 ] : "/tmp"; 
#$sDir = $ARGV[ 0 ] // "/tmp"; # Another form of defined a ? a : b from perl 5.9 
print "The dir is: $sDir\n";

# Mutiple candidate values
# getlogin
#	The current login from /etc/utmp
# getpwuid --> get entry record( list ) from passwd file:
#	$name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire
# $< uid, $> euid
my $sUser = $ENV{ USER } or $ENV{ LOGNAME } or 
            getlogin( ) or ( getpwuid( $< ) )[ 0 ] or 
			"Unknown uid number $<";  

################################### Using List ###################################
my @aNums = ( 1 .. 10 );
my @aSeconds = ( 101 .. 110 );
my @aTest = ( 35, 36 );
# || puts its left oprand into scalar context.
my @aDefaultList = @aNums || @aSeconds; 

# Oops, list only has a single element 
# which is the number of element in the rvalue list
print "Oops, left operand of '||' is in a scalar context: [@aDefaultList]\n";

# || puts its right oprand into list context.
@aDefaultList = () || @aSeconds;
print "'||' puts its right oprand into list context: \n[@aDefaultList]\n";

# Multipls '||' test, || puts its right oprand into list context.
@aDefaultList = () || @aTest || @aSeconds;
print "Multiple '||', it puts its right oprand into list context: \n[@aDefaultList]\n";


# Or can support left oprand in list context
@aDefaultList = @aNums or @aSeconds; 
print "'Or' can support left operand's list context: [@aDefaultList]\n";

# Or has a low priority than '='
@aDefaultList = () or @aSeconds;
print "Oops, 'Or' has a low piority than '=': [@aDefaultList]\n";

@aDefaultList = ( () or @aSeconds );
print "Correct piority now: [@aDefaultList]\n";

# When setting default list in a list context: 
# Use: 1. if not ( unless ) 2. Tree-way test
@aNums = @aSeconds if not @aNums;  # Self update when list is null 
print  "Using if not to update list: @aNums\n";

# Three way testing, can have a choice, better than if not
@aDefaultList = ( ) ? @aNums : @aSeconds;
print "Using three-way testing: @aDefaultList\n"; 


